Skip to content

Feat/canvas selection and inverted affordance#49

Merged
u8array merged 3 commits into
mainfrom
feat/canvas-selection-and-inverted-affordance
May 10, 2026
Merged

Feat/canvas selection and inverted affordance#49
u8array merged 3 commits into
mainfrom
feat/canvas-selection-and-inverted-affordance

Conversation

@u8array
Copy link
Copy Markdown
Owner

@u8array u8array commented May 10, 2026

No description provided.

u8array added 3 commits May 10, 2026 20:42
- Extract the previously-hardcoded indigo selection colour to
  CanvasColors.selection so per-shape strokes and the Konva Transformer
  share one source. Indigo stays (industry-standard for design tools);
  the UI accent (amber) remains separate on purpose — it would clash
  with B/W shape fills.
- Style the Transformer's borderStroke / anchorStroke / anchorFill /
  anchorSize explicitly so all selection visuals are coherent.
- Replace the line's solid-fill Circle endpoint handles with white
  Rect anchors that mirror the Transformer style (separate transparent
  hit-area Rect underneath); same look across line and other shapes.

Inverted-shape rendering left as-is: the existing difference-blend body
is print-correct (renders black on the white label, inverts darker
shapes underneath), so no extra affordance is needed.
…ed view

Root cause traced to a sub-pixel threshold in applyHeightSnap (introduced
in be6f2b8): the half-dot tolerance used to detect a top-anchor resize
becomes < 1 screen pixel at low zoom (1 dot < 2 px), Konva's per-frame
scale-driven node-position FP noise easily exceeds it, every frame is
falsely flagged as a top-anchor drag, and pinBottomEdge marches the box
up out of the work area. A second false positive on deriveActiveEdges
(0.5 px default tolerance) lets the resize-time object-snap pull a
bottom-edge resize sideways.

Fixes:

- applyHeightSnap is now a no-op for shapes without a row anchor. Boxes
  and 1D barcodes don't need per-frame integer-dot snapping during the
  drag — onTransformEnd already rounds via the global snap function.
  Only stacked-2D barcodes (PDF417 / MicroPDF417 / Codablock), where a
  non-integer row count is invalid, keep the row-quantising path with
  pinBottomEdge intact.
- deriveActiveEdges default tolerance bumped from 0.5 px to 2 px so FP
  drift on a single-edge drag doesn't flip a stationary edge to active
  and trigger a sideways snap.
- New pinInactiveEdges enforces the resize invariant explicitly: edges
  the user did NOT grab (>2 px from start) are restored to their
  start-of-drag positions after every boundBoxFunc pass.
- transformStartBboxRef is captured lazily on the first boundBoxFunc
  call (using its oldBox) instead of in onTransformStart via
  getClientRect. On a rotated parent group those two coord systems
  diverge; capturing the start in the same frame Konva emits keeps the
  pin / activeEdges math consistent.
- When viewRotation is non-zero, the whole height-snap / object-snap /
  pin pipeline is skipped — Konva's bbox semantics there don't map onto
  an axis-aware model. Native resize is used; smart-align during resize
  is disabled in rotated views (drag-time smart-align unaffected).

Adds 3 regression tests for applyHeightSnap covering the noop / row-snap
/ top-anchor pin paths.
The same '(e) => onSelect(shift||ctrl||meta)' click + 'onSelect(false)'
tap pair was duplicated 14 times across the four shape renderers
(KonvaObject, LineObject, ImageObject, BarcodeObject). Extracts a small
selectionHandlers(onSelect) helper next to the shared KonvaObjectProps
type so each renderer just spreads {...selectionHandlers(onSelect)} on
its outermost selectable node.
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request unifies selection visuals across canvas objects by introducing a centralized color scheme and shared selection handlers. It addresses sub-pixel drift issues during resizing by implementing an edge-pinning mechanism and increasing the tolerance for active edge detection. Additionally, it ensures selection outlines remain visible on inverted objects through a new overlay component and adds regression tests for line thickness and resize behavior. I have no feedback to provide as there were no review comments to evaluate.

@u8array u8array merged commit 6716848 into main May 10, 2026
2 checks passed
@u8array u8array deleted the feat/canvas-selection-and-inverted-affordance branch May 10, 2026 19:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant